#!/bin/bash
# Shell script which generates a Java program from a DDlog program and compiles it

# When running in CI, the DDlog compiler should be prinstalled by the build stage.
if [ -z "${IS_CI_RUN}" ]; then
    stack install
fi

if command clang -v 2>/dev/null; then
    export CC=clang
else
    export CC=gcc
fi

# "Returns" the name of the library to use.
# Should be invoked using $(libname), since bash
# functions cannot return strings.
function libname {
    if [[ -n "${LIBDDLOG}" ]]; then
        echo "${LIBDDLOG}"
    else
      case $(uname -s) in
        Darwin*)    echo "libddlogapi.dylib";;
        Linux*)     echo "libddlogapi.so";;
        *)          echo 1>&2 "Unsupported OS"; exit 1
      esac
    fi
}

# Compile a DDlog program and a Java program that uses it.
# Requires the flatbuf library to be installed and in the CLASSPATH
# the DDLFLAGS environment variable is passed as arguments to ddlog
# If the LIBDDLOG environment variable is set it is used as the name for the library
# The default library name is libddlogapi.(os-specific-extension)
function compile {
    local DLFILE=$1   # ddlog program that is being compiled
    local JAVAPROG=$2 # java test program that is being compiled
    local BUILD=$3    # one of "debug" or "release"

    if [[ "x${BUILD}" != "xdebug" && "x${BUILD}" != "xrelease" ]]; then
        echo "Third argument of compile must be 'debug' or 'release', not ${BUILD}"
        exit 1
    fi

    local DLPROG
    DLPROG=$(basename ${DLFILE} .dl)
    local DLDIR
    DLDIR=$(dirname ${DLFILE})
    if [ "x${DLDIR}" == "x" ]; then
        DLDIR="."
    fi

    CLASSPATH=$(pwd)/${DLDIR}/${DLPROG}_ddlog/flatbuf/java:$(pwd)/../ddlogapi.jar:..:.:$CLASSPATH
    # Compile the DDlog program
    ddlog ${DDLFLAGS} -i ${DLFILE} -L../../lib -j
    # Compile the generated rust program; generates ${DLDIR}/${DLPROG}_ddlog/target/${BUILD}/lib${DLPROG}_ddlog.a
    pushd ${DLDIR}/${DLPROG}_ddlog || exit 1
    if [ "x${BUILD}" == "xrelease" ]; then
        cargo build --features=flatbuf --release
    else
        cargo build --features=flatbuf
    fi
    popd || exit 1
    # Build the Java library with the DDlog API
    make -C ..
    # Build the generated Java classes for serialization (generated by flatbuf)
    (cd ${DLDIR}/${DLPROG}_ddlog/flatbuf/java && javac $(ls ddlog/__${DLPROG}/*.java) && javac $(ls ddlog/${DLPROG}/*.java))

    # Compile Java program
    javac -encoding utf8 -Xlint:unchecked ${JAVAPROG}

    case $(uname -s) in
        Darwin*)    JDK_OS=darwin; LINKER_FLAGS="-l${DLPROG}_ddlog -dynamiclib";;
        Linux*)     JDK_OS=linux; LINKER_FLAGS="-Wl,-static -l${DLPROG}_ddlog -Wl,-Bdynamic -shared" ;;
        *)          echo "Unsupported OS"; exit 1
    esac

    # Create a shared library containing all the native code: ddlogapi.c, ${DLPROG}_ddlog.a
    local LIBNAME
    LIBNAME=$(libname)
    ${CC} -Werror -std=gnu11 -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/${JDK_OS} -I${DLDIR}/${DLPROG}_ddlog -I../../lib ../ddlogapi.c -L${DLDIR}/${DLPROG}_ddlog/target/${BUILD} ${LINKER_FLAGS} -o ${LIBNAME}
}

function cleanup {
    local LIBNAME
    LIBNAME=$(libname)
    rm -rf ./*.class "${LIBNAME}"
}
